﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using ClassBuilder;
using ConsoleApp;

public static class Extensions
{
    /// <summary>
    /// 判断字符串是否为Null、空
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static bool IsEmpty(this string value)
    {
        return string.IsNullOrWhiteSpace(value);
    }


    /// <summary>
    /// 判断字符串是否不为Null、空
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static bool NotEmpty(this string value)
    {
        return !string.IsNullOrWhiteSpace(value);
    }


    /// <summary>
    /// 判断引用类型是Null
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static bool IsNull<T>(this T value)
        where T : class
    {
        return value == null;
    }

    /// <summary>
    /// 判断引用类型是不为Null
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value"></param>
    /// <returns></returns>
    public static bool NotNull<T>(this T value)
       where T : class
    {
        return value != null;
    }


    /// <summary>
    /// 是否是简单数据类型
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static bool IsSimpleType(this Type type)
    {
        Type t = Nullable.GetUnderlyingType(type) ?? type;
        if (t.IsPrimitive
            //|| t.IsEnum
            || t == typeof(string)
            //|| t.IsAssignableFrom(typeof(Guid))
            //|| t.IsAssignableFrom(typeof(DateTime))
            ) return true;
        return false;
    }


    /// <summary>
    /// 格式化
    /// </summary>
    /// <param name="value"></param>
    /// <param name="objs"></param>
    /// <returns></returns>
    public static string Format(this string value, params object[] objs)
    {
        if (value.IsEmpty())
        {
            return string.Empty;
        }
        return string.Format(value, objs);
    }


    /// <summary>
    /// 与字符串进行比较，忽略大小写
    /// </summary>
    /// <param name="value"></param>
    /// <param name="other"></param>
    /// <returns></returns>
    public static bool EqualsIgnoreCase(this string value, string other)
    {
        return value.Equals(other, StringComparison.OrdinalIgnoreCase);
    }


    /// <summary>
    /// 转换成Boolean
    /// </summary>
    /// <param name="s"></param>
    /// <returns></returns>
    public static bool ToBool(this object s)
    {
        if (s == null) return false;
        s = s.ToString().ToLower();
        if (s.Equals(1) || s.Equals("1") || s.Equals("true") || s.Equals("是") || s.Equals("yes"))
            return true;
        if (s.Equals(0) || s.Equals("0") || s.Equals("false") || s.Equals("否") || s.Equals("no"))
            return false;

        Boolean.TryParse(s.ToString(), out bool result);
        return result;
    }

    /// <summary>
    /// 转为首字母大写
    /// </summary>
    /// <param name="value">字符串</param>
    /// <returns></returns>
    public static string ToFirstUpperStr(this string value)
    {
        if (value.IsEmpty())
        {
            return string.Empty;
        }
        return value.Substring(0, 1).ToUpper() + value.Substring(1);
    }

    /// <summary>
    /// 转为首字母小写
    /// </summary>
    /// <param name="value">字符串</param>
    /// <returns></returns>
    public static string ToFirstLowerStr(this string value)
    {
        if (value.IsEmpty())
        {
            return string.Empty;
        }
        return value.Substring(0, 1).ToLower() + value.Substring(1);
    }

    /// <summary>
    /// 对字符串进行编码
    /// </summary>
    /// <param name="value">字符串</param>
    /// <returns></returns>
    public static string HtmlEncode(this string value)
    {
        if (value.IsEmpty())
        {
            return string.Empty;
        }
        return HttpUtility.HtmlEncode(value);
    }

    /// <summary>
    /// 对字符串进行解码
    /// </summary>
    /// <param name="value">字符串</param>
    /// <returns></returns>
    public static string HtmlDecode(this string value)
    {
        if (value.IsEmpty())
        {
            return string.Empty;
        }
        return HttpUtility.HtmlDecode(value);
    }


    /// <summary>
    /// 字符串的Md5值
    /// </summary>
    /// <param name="value">字符串</param>
    /// <returns></returns>
    public static string Md5(this string value)
    {
        if (value == null)
            return null;
        MD5 md5Hash = MD5.Create();
        byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(value));
        StringBuilder sBuilder = new StringBuilder();
        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }
        return sBuilder.ToString();
    }

    public static void AddHashSet<K, V>(this IDictionary<K, HashSet<V>> @this, K key, params V[] values)
    {
        if (values == null || values.Length == 0) return;
        HashSet<V> lstValue = new HashSet<V>();
        if (!@this.TryGetValue(key, out lstValue))
        {
            lstValue = new HashSet<V>();
            foreach (var item in values)
            {
                lstValue.Add(item);
            }
            @this.Add(key, lstValue);
        }
        else
        {
            foreach (var item in values)
            {
                lstValue.Add(item);
            }
            @this.Remove(key);
            @this.Add(key, lstValue);
        }
    }

    public static string NoHtml(this string value)
    {
        var str = value?.HtmlDecode();

        if (str.Contains("<pre"))
        {
            str = Regex.Replace(str, @"<pre>(.|\n)+?</pre>", "", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);
        }

        #region url链接地址 去除
        HashSet<string> lst = new HashSet<string>();
        var matches = Regex.Matches(str, "((.|\n)+?)((https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|])((.|\n)+?)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);

        for (int k = 0; k < matches.Count; k++)
        {
            var match = matches[k];
            var tmpStrs = new List<string>();
            for (int j = 1; j < match.Groups.Count; j++)
            {
                if (j != 2 && j != 4 && j != 6)
                {
                    var s = match.Groups[j].Value;
                    tmpStrs.Add(s);
                    lst.Add(s);
                }
            }

            if (k == matches.Count - 1)
            {
                var last_str = str.Substring(str.LastIndexOf(tmpStrs.Last()));
                lst.Add(last_str);
            }
        }

        if (lst.Any())
        {
            str = string.Join("", lst);
        }

        #endregion

        //保留 a标签的链接地址
        str = Regex.Replace(str, "((.|\n)+?)<a.+href=\"(.+?)\".*?>(.*?)</a>((.|\n)+?)", "$1$4：$3$5", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled);

        return Regex.Replace(str, @"<.+?>|'", "", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Multiline);
    }

    #region ECharts

    /// <summary>
    /// 枚举值 唯一Id
    /// </summary>
    /// <param name="members"></param>
    /// <returns></returns>
    public static string MId(this string[] members)
    {
        Array.Sort(members);
        return string.Join("", members).Md5();
    }

    public static string CheckDesc(this string desc)
    {
        var lines = desc.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
        lines = lines.Where(line => (!line.StartsWith("例如") && !line.EndsWith("：")) || line.EndsWith("效果：")).ToArray();
        var list = new List<string>();
        foreach (var line in lines)
        {
            if (line.Contains("如下示例："))
            {
                break;
            }
            list.Add(line.Replace("：", "。"));
        }
        return string.Join("\r\n", list);
    }


    public static List<string> NameSpaceDirs(this CSClass cls)
    {
        var newCls = cls.Tag as CSClass;
        List<string> lst = new List<string>();
        while (true)
        {
            if (newCls != null)
            {
                lst.Add(newCls.ClassName.ToFirstUpperStr());
                newCls = newCls.Tag as CSClass;
            }
            else
            {
                break;
            }
        }
        lst.Reverse();
        return lst;
    }


    /// <summary>
    /// 切割字符串
    /// </summary>
    /// <param name="value"></param>
    /// <param name="separator">分隔符</param>
    /// <returns></returns>
    public static string[] GoSplit(this string value, StringSplitOptions options = StringSplitOptions.None, params string[] separator)
    {
        return value?.Split(separator, options);
    }



    /// <summary>
    /// 分词(遇到大写字母则切割)
    /// lineStyleType => line/Style/Type
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static List<string> Segment(this string value)
    {
        if (value.IsEmpty())
        {
            return new List<string>();
        }

        var lst = new List<string>();
        if (!Regex.IsMatch(value, "[A-Z]", RegexOptions.Compiled))
        {
            lst.Add(value);
            return lst;
        }

        var cursor = 0;
        var strs = value.ToCharArray().Select(s => s.ToString()).ToArray();
        for (int j = 0; j < strs.Length; j++)
        {
            var chr = strs[j];
            if (j != 0 && Regex.IsMatch(chr, "^[A-Z]$", RegexOptions.Compiled))
            {
                var tmp = value.Substring(cursor, j - cursor);
                lst.Add(tmp);
                cursor = j;
            }
        }
        lst.Add(value.Substring(cursor, strs.Length - cursor));
        cursor = 0;
        return lst;
    }





    public static string JsonNodeName(this CSClass cls, string propName)
    {
        List<string> lst = new List<string>();
        while (true)
        {
            if (cls != null)
            {
                lst.Add(cls.ClassName.ToFirstLowerStr());
                cls = cls.Tag as CSClass;
            }
            else
            {
                break;
            }
        }
        lst.Reverse();
        //前2个去掉，EChartsOption、以及最初用到的类名
        lst.RemoveRange(0, 2);
        lst.Add(propName?.ToFirstLowerStr());
        return string.Join(".", lst);
    }


    public static CSClass TagClass(this CSClass cls)
    {
        var newCls = cls.Tag as CSClass;
        return newCls;
    }

    /// <summary>
    /// 类根据命名空间生成 指定路径 类文件
    /// </summary>
    /// <param name="cls"></param>
    public static void ClassWriteFile(this CSClass cls)
    {
        if (cls.All_Prop.Count > 0)
        {
            var lst = cls.NameSpaceDirs();
            lst.Remove("EChartsOption");
            lst.Insert(0, Download.ClassPath);
            var newDir = Path.Combine(lst.ToArray());
            if (!Directory.Exists(newDir))
            {
                Directory.CreateDirectory(newDir);
            }

            var writePath = string.Empty;
            if (Directory.Exists(Path.Combine(newDir, cls.ClassName)))
            {
                cls.NameSpace = cls.TagClass()?.NameSpace + "." + cls.ClassName;
                lst.Add(cls.ClassName);
                lst.Add(cls.ClassName + ".cs");
                writePath = Path.Combine(lst.ToArray());
            }
            else
            {
                cls.NameSpace = cls.TagClass()?.NameSpace ?? Download.Default_NameSpace;
                lst.Add(cls.ClassName + ".cs");
                writePath = Path.Combine(lst.ToArray());
            }
            File.WriteAllText(writePath, cls.Value, Encoding.UTF8);
        }
    }

    #endregion

}